package com.cqs.example.io;

import com.alibaba.fastjson.util.IOUtils;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.DeflaterOutputStream;

/**
 * @Author lixw
 * @Date 7/19/20 9:23 PM
 */
@Data
@Slf4j
public class IoBean implements Serializable {
    private final static long  serialVersionUID = 6844044558331513855L;
    private String name = "";

//    private final long id = System.currentTimeMillis();
    private final long id = 1000L;

    private byte[] date = "当前大部分后端服务都是基于微服务架构实现的。服务按照业务划分被拆分，实现了服务的解偶，但同时也带来了新的问题，不同业务之间通信需要通过接口实现调用。两个服务之间要共享一个数据对象，就需要从对象转换成二进制流，通过网络传输，传送到对方服务，再转换回对象，供服务方法调用。这个编码和解码过程我们称之为序列化与反序列化。".getBytes();

    public static final String DIR = "data/io/bean/";

    static {
        Lists.newArrayList("jdk","kryo").stream().forEach(it->{
            File dir =new File(String.format(DIR + it));
            if (!dir.exists()) {
                dir.mkdirs();
            }
        });

    }
    /**
     * Read the map in using a custom routine.
     */
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
    }

    /**
     * Write the map out using a custom routine.
     */
    private void writeObject(ObjectOutputStream out) throws IOException {
        Set root = new HashSet();
        Set s1 = root;
        Set s2 = new HashSet();
        for (int i = 0; i < 100; i++) {
            Set t1 = new HashSet();
            Set t2 = new HashSet();
            t1.add("foo"); // 使 t2 不等于 t1
            s1.add(t1);
            s1.add(t2);
            s2.add(t1);
            s2.add(t2);
            s1 = t1;
            s2 = t2;
        }
        s1.equals(s2);
        log.info("测试了");
        out.defaultWriteObject();
    }

    public static String jdkSerialToFile(IoBean bean){
        ObjectOutputStream oos = null;
        FileOutputStream fos = null;
        File file  = new File(String.format("%s/jdk_%d",DIR,bean.getId()));
        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(bean);
//            oos.writeLong(bean.getId());
//            oos.write(bean.getName().getBytes());
//            oos.write(bean.getDate());
            oos.flush();
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtils.close(oos);
            IOUtils.close(fos);
        }
        return file.getAbsolutePath();
    }

    public static String kryoSerialToFile(IoBean bean){
        Kryo kryo = new Kryo();
        kryo.register(IoBean.class);
        IoBean ioBean = mockBean0();
        File file  = new File(String.format("%s/kryo/%d",DIR,bean.getId()));
        OutputStream os = null;
        Output output = new Output(100, -1);
        try {
            os = new DeflaterOutputStream(new FileOutputStream(file));
            kryo.writeObject(output, ioBean);
        } catch (FileNotFoundException e) {
            return null;
        }finally {
            output.close();
            IOUtils.close(os);
        }
        return file.getAbsolutePath();

    }
    public static IoBean jdkDeserializeFromFile(String file){

        ObjectInputStream ois = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream( new File(file));
            ois = new ObjectInputStream(fis);
            log.info("size:{}",fis.available());
            Object o = ois.readObject();
            IoBean bean = (IoBean) o;
            log.info("size:{},反序列化:{}",fis.available(), bean.getId());
            return bean;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }finally {
            IOUtils.close(ois);
            IOUtils.close(fis);
        }
    }

    public static byte[] jdkSerial(IoBean bean) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(baos);
            oos.writeObject(bean);
            oos.flush();
            return baos.toByteArray();
        } catch (IOException e) {
            return null;
        } finally {
            IOUtils.close(oos);
            IOUtils.close(baos);
        }
    }


    public static byte[] byteBufferSerial(IoBean bean) {
        byte[] nameBytes = bean.getName().getBytes();
        ByteBuffer buffer = ByteBuffer.allocate(8 + nameBytes.length + bean.getDate().length);
        //long是8字节
        buffer.putLong(bean.id);
        buffer.put(nameBytes);
        buffer.put(bean.date);
        buffer.flip();
        return buffer.array();
    }

    public static byte[] kryoSerial(IoBean bean) {
        Kryo kryo = new Kryo();
        kryo.register(IoBean.class);
        Output output = new Output(100, -1);
        kryo.writeObject(output, bean);
        return output.getBuffer();
    }

    public static byte[] kyroDeserialize(IoBean bean){
        return null;
    }

    public void test(){
        log.info("这是原始的测试方法");
    }


    public static IoBean mockBean0(){
        IoBean ioBean = new IoBean();
        ioBean.setName("张三");
        return ioBean;
    }


    public static void main(String[] args) {
//        jdkSerialToFile(mockBean0());
        jdkDeserializeFromFile("/home/li/IdeaProjects/spring-cloud/data/io/bean/jdk_1000");

    }

}
